<?php
    /**
     * public公共成员：公开的，没必要隐藏的数据信息。可在程序任何位置（类内、类外）被其他的类和对象调用。子类可以继承何使用
     * 父类中所有的公共成员
     * private私有成员，只能在所属类的内部被调用和修改，不可以在类外被访问。在子类中也不可以。
     */
    class Book{
        private $name='computer';
        public function  setname($name){
            $this->name=$name;
        }
        public function getname(){
            return $this->name;
        }
    }
    class Lbook extends Book{

    }
    $lbook=new Lbook();
    echo '正确操作私有变量的方法';
    $lbook->setname("php从入门到应用");
    echo $lbook->getname();
    echo '<br>直接操作私有变量的结果：';
    //echo Book::$name;//错误操作私有变量   不会输出
/**
 * protected保护成员
 * 这些类做到封装以后，希望子类能够调用，但对其它的类来说，还要做到封装，就可以使用protected关键字
 */
    class Book1{
        protected $name='computer';
    }
    class lbook1 extends Book1{
        public function showme(){
            echo '对于protected修饰的变量，在子类中是剋直接调用的。如：$name='.$this->name;
        }
    }
    $lbook=new lbook1();
    $lbook->showme();
    echo '<p>在其他的地方是不可以调用的，否则：';
/**
 * Fatal error: Uncaught Error: Cannot access private property Book::$name in C:\Users\hhl91\PhpstormProjects\text\数据隐藏.
 * php:24 Stack trace: #0 {main} thrown in C:\Users\hhl91\PhpstormProjects\text\数据隐藏.php on line 24
 * $lbook->name='history';
 */


/**
 * 静态变量
 * self，在类内部调用静态成员是所使用
 * 静态成员所在的类名，在类外调用类内部的静态成员时所用。
 */
    class book2{
        static $num=0;
        public function showme(){
            echo '您是第'.self::$num.'位访客';
            self::$num++;
        }
    }
    $lbook=new book2();
    $lbook->showme();
    echo '<br>';
    $lbook2=new book2();
    $lbook2->showme();
    echo '<br>';
    echo '您是第'.book2::$num.'位访客';
/**
 * final关键字
 * final在中文中的 意思是最终的，被final修饰过的类和方法就是最终的版本。
 * 该类不能被继承也不能再有子类
 * 该方法不可能被重写，也不可以被覆盖
 */
    final class book3{
        function _construct()
        {
            echo '最终的 object';
        }
    }

/**
 * 抽象类
 * 抽象类是一种不能被实例化的类，只能作为其他类 的父类来使用。抽象类使用
 * obstract关键字来声明
 */
    abstract class commodityobject{
        abstract function service($getname,$price,$num);
    }
    class mybook extends commodityobject{
        function service($getname, $price, $num)
        {
            // TODO: Implement service() method.
            echo '您购买的商品是'.$getname.'该商品的价格为'.$price.'元。您购买的数量为：'.$num.'本';
        }
    }
    class mycomputer extends commodityobject{
        function service($getname, $price, $num)
        {
            // TODO: Implement service() method.
            echo '您购买的商品是'.$getname.'该商品的价格为'.$price.'元。您购买的数量为：'.$num.'台';
        }
    }
    $book=new mybook();
    $book->service('记事本','5.5',20);
    echo '<br>';
    $computer=new mycomputer();
    $computer->service('苹果笔记本','8000','10');
    echo '<br>';
/**
 * 接口的使用
 * php只支持单继承，不支持多重继承。如果想实现多重继承，就要使用接口类。
 * 接口类通过interface关键字来声明，并且类中只能包含为实现的方法和一些成员变量。
 * 子类是通过implements关键字类实现接口
 */
    interface mpopedom{
        function popedom();
    }
    interface mpurview{
        function purview();
    }
    class member implements  mpurview{
        function purview()
        {
            // TODO: Implement purview() method.
            echo '会员拥有权限<br>';
        }
    }
    class manager implements mpurview,mpopedom{
        function popedom()
        {
            // TODO: Implement popedom() method.
            echo '管理员拥有会员的全部权限<br>';
        }
        function purview()
        {
            // TODO: Implement purview() method.
            echo '管理员还有会员没有的权限<br>';
        }
    }
    $member=new member();
    $member->purview();
    echo '<p>';
    $manager=new manager();
    $manager->popedom();
    $manager->purview();
    echo '<p>';
/**
 * 魔术方法
 * 以  __ (两个下划线)开头的方法
 * 这些是创建类的时候的php自动包含的一些方法
 * php中保留了所有以“__”开头的方法，可以使用php文档中已有的方法，不要自己创建
 * 注意 魔术方法均用public关键字修饰
 */
    class student
    {
        private $a;
        private $b = 0;
        public $c;
        public $d = 0;

        public function __get($name)
        {
            // TODO: Implement __get() method.
            return 123;
        }
        public function __set($name, $value)
        {
            // TODO: Implement __set() method.
            echo 'this is set function<br>';
        }
    }
    $s=new student();
    var_dump($s->a);
    var_dump($s->b);
    var_dump($s->c);
    var_dump($s->d);
    var_dump($s->e);
    $s->a=3;
    $s->c=3;
    $s->f=3;
/**
 * int(123) private
 * int(123) private
 * NULL   未设置public
 * int(0) 0public
 * int(123) 未定义
 * this is set function
 * public c set 3 成功了，所以没有输出
 * this is set function
 */
    class SportObject9{
        public function myDream(){
            echo '调用的方法存在，直接执行此方法。<br>';
        }
        public function __call($name, $arguments)
        {
            // TODO: Implement __call() method.
            echo '方法不存在，则执行__call（）方法。<br>';
            echo '方法名为：'.$name.'<br>';
            echo '参数有：';
            echo '<pre>';
            print_r($arguments);
        }
    }
    $exam=new SportObject9();
    $exam->myDream();
    $exam->mDream('how','what','why');
/**
 * 调用的方法存在，直接执行此方法。
方法不存在，则执行__call（）方法。
方法名为：mDream
参数有：

Array
(
[0] => how
[1] => what
[2] => why
)
 */
    class SportObject10{
        private $type='DIY';
        public function __toString()
        {
            return $this->type;//方法返回私有变量$tpye的值
            // TODO: Implement __toString() method.
        }
    }
    $mycomputer=new SportObject10();
    echo '对象$mycomputer的值为：'.$mycomputer.'<br>';
/**
 * 对象$mycomputer的值为：DIY
 */


/**
 * 通常用include()或require（）函数在一个php文件中引入类文件。‘
 * require('a.php');
 * $a=new a();
 */
    function __autoload($classname){
        $class_path=$classname.'php文件路径';
        if (exists($class_path)){
            include_once ($class_path);
        }else{
            echo '类路径错误';
        }
    }
    ?>
